import { createApp, Directive, App } from "vue";
import { id, name } from "./config";
import Message, { MessageExpose } from "./Message.vue";

// 自定义消息
class CustomMessage {
  $message?: MessageExpose;

  constructor() {
    const MessageContainerId = id;
    const MessageContainer = document.createElement("div");
    MessageContainer.setAttribute("id", MessageContainerId);

    document.body.appendChild(MessageContainer);

    setTimeout(() => {
      this.$message = createApp(Message).mount(
        `#${id}`
      ) as any as MessageExpose;
    }, 0);
  }

  show(msg = "") {
    if (this.$message) {
      this.$message?.show(msg);
    }
  }
}

let customMessage: CustomMessage;

// 初始化
function init() {
  if (!customMessage) {
    customMessage = new CustomMessage();
  }
}

// 自定义指令
interface ClickShowMessageData {
  el: Element;
  msg: string;
  handler?(e: MouseEvent): void;
}

const ClickShowMessageDataList: ClickShowMessageData[] = [];

function handleClick(this: ClickShowMessageData) {
  customMessage.show(this.msg);
}

export const directive: Directive<HTMLElement, string | number> = {
  mounted(el, binding) {
    init();

    const msg = binding.value.toString();

    if (!msg) {
      throw new Error("v-message 需要赋值消息内容");
    }

    // 设置数据
    const clickOutsideData: ClickShowMessageData = { el, msg };
    clickOutsideData.handler = handleClick.bind(clickOutsideData);

    // 绑定事件
    el.addEventListener("click", clickOutsideData.handler);
    // 加入数据列表
    ClickShowMessageDataList.push(clickOutsideData);
  },

  unmounted(el) {
    const findIndex = ClickShowMessageDataList.findIndex(
      (item) => item.el === el
    );
    const findObj = ClickShowMessageDataList[findIndex];

    // 解绑事件
    if (findObj && findObj.handler) {
      el.removeEventListener("click", findObj.handler);
    }
    // 移出数据列表
    ClickShowMessageDataList.splice(findIndex, 1);
  },
};

export function useMessage() {
  return customMessage;
}

export default {
  install(app: App) {
    init();
    // 注册指令
    app.directive(name, directive);
    // 全局方法
    app.config.globalProperties.$customMessage = customMessage;
  },
};
